
#include <stdio.h>
#include <unistd.h>
#include <string.h>

#include "dana_osd.h"

#include "ak_common.h"
#include "ak_vi.h"
#include "ak_osd.h"
#include "ak_osd_ex.h"
#include "ak_thread.h"
#include "ak_config.h"

#define FULL_SCREEN 	0

struct dana_osd_info {
	/* if osd function enable, set 1 */
	unsigned char run_flag;
	/* if switch_flag == 1, display osd name */
	unsigned char switch_flag;
	ak_pthread_t tid;
	struct osd_ex_info ex;

	struct ak_timeval tv_start;
	struct ak_timeval tv_end;
};

static struct dana_osd_info dana_osd = {0};

/**
 * set_osd_buffer - set osd buff 
 * @vi_handle[IN]: opened vi handle  
 * return: 0, success; -1, failed.
 */
static int set_osd_buffer(void *vi_handle)
{
	int channel = 0;
	
	for (channel = 0; channel < 2; channel++) {
		int width = 0;
		int height = 0;
		int y_start = 0;
		int max_w, max_h;

		if (ak_osd_get_max_rect(channel, &max_w, &max_h) < 0) {
			ak_print_error_ex("chn=%d, ak_osd_get_max_rect failed\n", channel);
			return AK_FAILED;
		}
		ak_print_normal_ex("chn=%d, ak_osd_get_max_rect OK, max_w: %d max_h: %d\n",
			channel, max_w, max_h);
			
		width =  max_w;
#if(FULL_SCREEN)
		height = max_h;
#else
		height = (0 == channel)? OSD_EX_FONT_SIZE * 2 * 2 : OSD_EX_FONT_SIZE * 2;
#endif
		/* leftdown   or  rightdown  */
		if( 1 == dana_osd.ex.position || 4 == dana_osd.ex.position) {
			y_start = max_h - height;
		}
		
		if (ak_osd_set_rect(vi_handle, channel, 0, y_start, width, height) < 0) {
			ak_print_error_ex("chn=%d, ak_osd_set_rect failed\n", channel);
			return AK_FAILED;
		}
		
		ak_print_normal("chn=%d, ak_osd_set_rect OK\n", channel);
	}

	return AK_SUCCESS;
}

/**
 * init_osd_env - init osd var, include position and format 
 * return: void.
 */
static void init_osd_env(void)
{
	struct camera_disp_config* pcamera_info = ak_config_get_camera_info();
 	
	/* 
	 * display osd on 4 position: 
	 *	2-"leftup",1-"leftdown",3-"rightup",4-"rightdown" 
	 */
	dana_osd.ex.position = pcamera_info->osd_position;
	strcpy(dana_osd.ex.name, pcamera_info->osd_name);
	dana_osd.ex.time_switch = pcamera_info->time_switch;
	dana_osd.ex.date_format = pcamera_info->date_format;
	dana_osd.ex.hour_format = pcamera_info->hour_format;
	dana_osd.ex.week_format = pcamera_info->week_format;
	dana_osd.switch_flag = pcamera_info->osd_switch;
	
	int main_width = pcamera_info->main_width; 	
	int sub_width = pcamera_info->sub_width;
	
	dana_osd.ex.ypos_main = 0;
	dana_osd.ex.ypos_sub = 0;
	switch (dana_osd.ex.position) {
	case 1:	//leftdown		
#if(FULL_SCREEN)
		dana_osd.ex.ypos_main = pcamera_info->main_height - OSD_EX_FONT_SIZE * 4;
		dana_osd.ex.ypos_sub = pcamera_info->sub_height - OSD_EX_FONT_SIZE * 2;;
#endif	
	case 2:	//leftup
		dana_osd.ex.xpos_main = OSD_EX_FONT_SIZE * 2;		
		dana_osd.ex.xpos_sub = OSD_EX_FONT_SIZE;		
		dana_osd.ex.on_right_side = 0;
		break;

	case 4: //rightdown 	
#if(FULL_SCREEN)
		dana_osd.ex.ypos_main = pcamera_info->main_height - OSD_EX_FONT_SIZE * 4;
		dana_osd.ex.ypos_sub = pcamera_info->sub_height - OSD_EX_FONT_SIZE * 2;
#endif	
	case 3:	//rightup		
		dana_osd.ex.xpos_main	= main_width;		
		dana_osd.ex.xpos_sub	= sub_width;		
		dana_osd.ex.on_right_side	= 1;
		break;
	default:
		break;
	}
}

/**
 * dana_osd_thread - draw osd to screen on dana platform
 * @vi[IN]: vi handle  
 * return: null.
 */
static void *dana_osd_thread(void *vi_handle)
{
	ak_print_normal_ex("thread id: %ld\n", ak_thread_get_tid());
	ak_thread_set_name("dana_osd");
	
	struct osd_ex_info osd_ex = {0};

	memcpy(osd_ex.name, dana_osd.ex.name, sizeof(dana_osd.ex.name));
	osd_ex.on_right_side = dana_osd.ex.on_right_side;
	osd_ex.date_format = dana_osd.ex.date_format;
	osd_ex.week_format = dana_osd.ex.week_format;
	osd_ex.xpos_main = dana_osd.ex.xpos_main;
	osd_ex.ypos_main = dana_osd.ex.ypos_main;
	osd_ex.xpos_sub = dana_osd.ex.xpos_sub;
	osd_ex.ypos_sub = dana_osd.ex.ypos_sub;
	
	if(1 == dana_osd.switch_flag) {
		ak_osd_ex_disp_name(&osd_ex);
	}

	ak_get_ostime(&dana_osd.tv_end);
	ak_print_notice_ex("create thread --> disp osd time=%ld\n", 
		ak_diff_ms_time(&dana_osd.tv_end, &dana_osd.tv_start));
	while(dana_osd.run_flag && dana_osd.ex.time_switch) {
		if(ak_osd_ex_disp_date_time(&osd_ex) < 0)
			break;
			
		ak_sleep_ms(100);
	}

	ak_print_normal_ex("### thread id: %ld exit ###\n", ak_thread_get_tid());	
	ak_thread_exit();
	return NULL;
}

/**
 * dana_osd_get_ptr - get dana osd info ptr
 * @void: 
 * return: ptr of dana osd
 */
struct osd_ex_info* dana_osd_get_ptr(void)
{
	return &dana_osd.ex;
}

/**
 * dana_osd_init - create thread to draw osd to screen on dana platform
 * @vi[IN]: vi handle  
 * return: 0 - success, fail return -1.
 */
int dana_osd_init(void *vi_handle)
{
	if (ak_osd_ex_init_env(vi_handle)) {
		return AK_FAILED;
	}

	init_osd_env();
	if (set_osd_buffer(vi_handle)) {
		ak_osd_destroy();
		return AK_FAILED;
	}

	dana_osd.run_flag = AK_TRUE;
	ak_get_ostime(&dana_osd.tv_start);
	/* create one thread to draw osd on screen */
	int ret = ak_thread_create(&dana_osd.tid, dana_osd_thread,
        vi_handle, ANYKA_THREAD_MIN_STACK_SIZE, -1);
	if(ret){
		ak_print_normal_ex("create dana_osd_thread failed, ret=%d!\n", ret);
		dana_osd.run_flag = AK_FALSE;
	} else {
		ak_print_notice_ex("dana osd start\n\n");
	}

	return ret;
}

/**
 * dana_osd_exit - exit osd thread which is for dana platform  
 * return: void.
 */
void dana_osd_exit(void)
{
	if(dana_osd.run_flag){
		dana_osd.run_flag = AK_FALSE;
		ak_print_notice_ex("join dana_osd_thread\n");
		ak_thread_join(dana_osd.tid);
	}
	
	ak_print_notice_ex("dana_osd_thread join OK\n");
}
